<?php
class VerifyCode {
	private $width;
	private $height;
	private $verifyCodeNum;  //验证码字符个数
	private $img;  //图像资源
	private $disturbDotNum;  //干扰点个数
	private $arc;  //是否画弧线干扰
	private $verifyCodes;  //验证码
	
	public function __construct($width=80,$height=20,$verifyCodeNum=4,$arc=false) {
		$this->width = $width;
		$this->height = $height;
		$this->verifyCodeNum = $verifyCodeNum;
		$this->arc = $arc;
		
		//貌似php中设置颜色的总共次数是240 250次左右
		$number = floor($width*$height/20);
		if($number > 240-$verifyCodeNum) {
			$this->disturbDotNum = 240-$verifyCodeNum;
		} else {
			$this->disturbDotNum = $number;
		}
		$this->verifyCodes = $this->productCode();
	}
	
	//创建画布
	private function createImage() {
		//创建图像资源
		$this->img = imagecreatetruecolor($this->width, $this->height);
		$borderColor = imagecolorallocate($this->img, 0, 0, 0);  // 创建颜色
		$backColor = imagecolorallocate($this->img, mt_rand(225,255), mt_rand(225,255), mt_rand(225,255));
		//填充背景色 这时才真正有颜色
		imagefill($this->img,0,0,$backColor);
		//添加边框
		imagerectangle($this->img,0,0,$this->width-1,$this->height-1,$borderColor);
	}	
	
	//设置干扰元素
	private function setDisturbInfo() {
		//画干扰点
		for($i=0;$i<$this->disturbDotNum;$i++) {
			$dotColor = imagecolorallocate($this->img, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
			imagesetpixel($this->img, mt_rand(1,$this->width-2), mt_rand(1,$this->height-2), $dotColor);
		}
		//画弧线
		if($this->arc) {
			for($i=0;$i<3;$i++) {
				$arcColor = imagecolorallocate($this->img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
				//1资源  2-3圆心位置  4-5圆弧宽度和高度  6-7角度  8颜色
				imagearc($this->img,mt_rand(-5,$this->width+5),mt_rand(-5,$this->height+5),
					mt_rand(floor($this->width/2),$this->width+60),mt_rand(floor($this->height/2),$this->height+20),30,150,$arcColor);
			}
		}
		
	}

	//设置随机文本
	private function setText($fontFace = '') {
		for($i=0; $i<$this->verifyCodeNum; $i++) {
			$fontColor = imagecolorallocate($this->img, mt_rand(0,100), mt_rand(0,100), mt_rand(0,120));
			if(empty($fontFace)) {
				$fontSize = mt_rand(16,20);  //非像素
				$x = floor($this->width / $this->verifyCodeNum * $i + 3);  //横坐标开始位置
				$y = mt_rand(2,$this->height - 15);  //纵坐标开始位置
				imagechar($this->img, $fontSize, $x, $y, substr($this->verifyCodes,$i,1), $fontColor);
			} else {
				$fontSize = mt_rand(15, 17);  //字体大小 像素
				$x = floor(($this->width-8) / $this->verifyCodeNum * $i + 8);  //因为字体要倾斜所以留出8像素
				$y = mt_rand($fontSize, $this->height - 4);
				imagettftext($this->img, $fontSize, mt_rand(-10,10),
						$x, $y, $fontColor, $fontFace, substr($this->verifyCodes,$i,1));
			}
		}
	}
	//输出图像
	private function outputImage() {
		if(imagetypes() & IMG_GIF) {
			header("Content-Type:image/gif");
			imagegif($this->img);
		} else if(imagetypes() & IMG_JPG) {
			header("Content-Type:image/jpeg");
			imagejpeg($this->img);
		} else if(imagetypes() & IMG_PNG) {
			header("Content-Type:image/png");
			imagepng($this->img);
		} else {
			die('php不支持图像');
		}
	}
		
	//得到验证码字符串
	private function productCode() {
		$code = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ';
		$chars = '';
		for($i=0; $i<$this->verifyCodeNum; $i++) {
			$chars .= substr($code, mt_rand(0, strlen($code)-1), 1);
		}
		return $chars;
	}
	
	//关闭资源
	private function close() {
		if(isset($this->img)) {
			imagedestroy($this->img);
			$this->img = null;
		}
	}
	
	function __destruct() {
		if(isset($this->img)) {
			imagedestroy($this->img);
		}
	}
	
	//============用户调用的方法==========================
	//输出验证码图片
	public function showVerifyCodeImage($fontFace='') {
		//1.创建图片and背景
		$this->createImage();
		//2.设置干扰元素
		$this->setDisturbInfo();
		//3.输出随机文本
		$this->setText($fontFace);
		//4.输出图像
		$this->outputImage();
		//5.关闭资源
		$this->close();
	}
	
	//获得验证码字符串
	public function getVerifyCodes() {
		return $this->verifyCodes;
	}
}